package com.micro.controller;

import com.micro.download.DownloadM3u8;
import com.micro.entity.RequestHeader;
import com.micro.entity.TaskInfo;
import com.micro.form.AboutForm;
import com.micro.form.EditTaskForm;
import com.micro.form.SettingsForm;
import com.micro.global.ConfigInfo;
import com.micro.global.TaskInfoDataBase;
import com.micro.global.MainTaskTreadPool;
import com.micro.utils.HttpUtil;
import com.micro.utils.JsonUtil;
import com.micro.utils.ProcessUtil;
import com.micro.utils.SeriaUtil;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.Label;
import javafx.scene.control.TableView.TableViewSelectionModel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author dufen
 */
@Slf4j
public class MainController implements Initializable {
    /**
     * 循环监测线程池
     */
    private final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
    @FXML
    public TableView<TaskInfo> tableView;
    File file = new File("db.obj");
    @FXML
    private CheckMenuItem rebootCheck;
    @FXML
    private CheckMenuItem dormancyCheck;
    @FXML
    private CheckMenuItem shutdownCheck;
    @FXML
    private TableColumn speed;
    @FXML
    private Label state;

    private boolean isRefresh = true;

    @SneakyThrows
    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        //表格多选
        tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        //初始化数据到内存
        try {
            //如果原数据损坏则读取备份的数据，并重新下载
            initDatabase();
        }catch (Exception e){
            SeriaUtil.restoreDataBase();
        }
        Platform.runLater(() -> {
            startUnfinishedTasks();
        });
        threadPoolExecutor.execute(() -> {
            refreshTable();
        });

    }


    @SneakyThrows
    public void refreshTable() {
        log.info("调用刷新数据方法");
        while (isRefresh) {
            TaskInfoDataBase.DATABASE.stream().sorted(Comparator.comparing(t -> Integer.valueOf(t.getId()))).map(taskInfo -> {
                taskInfo.setId(TaskInfoDataBase.DATABASE.indexOf(taskInfo) + 1);
                return taskInfo;
            }).collect(Collectors.toList());
            tableView.setItems(TaskInfoDataBase.DATABASE);
            tableView.refresh();
            if (MainTaskTreadPool.getINSTANCE().getCorePoolSize() != ConfigInfo.getConfigInfo().getTaskCoreSize()) {
                MainTaskTreadPool.getINSTANCE().setCorePoolSize(ConfigInfo.getConfigInfo().getTaskCoreSize());
            }
            if (ConfigInfo.isIsShutdown()) {
                ProcessUtil.executeCommand("shutdown", "/s");
            }
            //间隔200毫秒
            TimeUnit.MILLISECONDS.sleep(1000);
        }
    }

    /**
     * 载入已添加的任务
     */
    private void startUnfinishedTasks() {
        TaskInfoDataBase.DATABASE.stream().filter(taskInfo -> !taskInfo.isComplete())
                .forEach(taskInfo -> {
                    //判断任务是否已经添加
                    if (StringUtils.contains(taskInfo.getUrl(), ".m3u8")) {
                        log.info("添加任务：{},链接：{},是否完成：{}", taskInfo.getName(), taskInfo.getUrl(), taskInfo.isComplete());
                        int coreSize = ConfigInfo.getConfigInfo().getDownCoreSize();
                        DownloadM3u8 download = new DownloadM3u8(taskInfo, coreSize == 0 ? 8 : coreSize);
                        MainTaskTreadPool.getINSTANCE().execute(download);
                        taskInfo.setOperation("载入任务");
                    }
                });
    }


    /**
     * 获取选中的任务
     *
     * @return
     */
    private List<TaskInfo> getTaskInfo() {
        TableViewSelectionModel<TaskInfo> selectionModel = tableView.getSelectionModel();
        //缓存集合，用于解决删除
        List<TaskInfo> taskInfos = new ArrayList<>();
        ObservableList<TaskInfo> selectedItems = selectionModel.getSelectedItems();
        selectedItems.stream().forEach(taskInfos::add);
        return taskInfos;
    }


    private void deleteFiles(TaskInfo taskInfo) {
        File cacheFile = new File(taskInfo.getCachePath());
        File[] files = cacheFile.listFiles();
        if (files != null) {
            for (File f : files) {
                try {
                    Files.delete(f.toPath());
                    log.info("删除成功,FileName:{},TaskName:{}", f.getName(), taskInfo.getName());
                } catch (Exception e) {
                    log.info("删除失败,FileName:{},TaskName:{}", f.getName(), taskInfo.getName());
                }
            }
        }
        try {
            Files.delete(cacheFile.toPath());
        } catch (IOException e) {
            log.info("缓存文件夹不存在");
        }
    }

    /**
     * 新增任务
     */
    public void newDataAction() {
        Platform.runLater(() -> {
            toAddForm(0, "NEW");
        });

    }

    public void importContent() {
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        try {
            Object data = clipboard.getData(DataFlavor.stringFlavor);
            if (data != null) {
                String content = String.valueOf(data);
                if(StringUtils.isNotBlank(content)){
                    if ((StringUtils.contains(content,".m3u8") && StringUtils.contains(content,"http"))==false) {
                        Alert alert = new Alert(Alert.AlertType.ERROR);
                        alert.setContentText("复制的内容不是正确的m3u8链接");
                        alert.show();
                        return;
                    }
                }
                String[] strs = StringUtils.split(content, "\n");
                int i = 0;
                for (String string : strs) {
                    TaskInfo taskInfo = new TaskInfo();
                    i = checkUrl(i, string, taskInfo);
                    if (StringUtils.isNotBlank(taskInfo.getUrl())) {
                        taskInfo.setCachePath("" + System.currentTimeMillis());
                        taskInfo.setFileInfos(Collections.emptyList());
                        TaskInfoDataBase.DATABASE.add(taskInfo);
                        int coreSize = ConfigInfo.getConfigInfo().getDownCoreSize();
                        DownloadM3u8 download = new DownloadM3u8(taskInfo, coreSize == 0 ? 8 : coreSize);
                        MainTaskTreadPool.getINSTANCE().execute(download);
                    }
                }
            } else {
                JOptionPane.showMessageDialog(null, "复制数据格式:\n第12集$https://cdn.605-zy.com/20211005/OqwayC2G/index.m3u8\n" +
                        "第13集$https://cdn.605-zy.com/20211014/Zf3VrVxK/index.m3u8\n" +
                        "第14集$https://cdn.605-zy.com/20211019/ewadEVAV/index.m3u8\n" +
                        "第15集$https://cdn.605-zy.com/20211026/2fyHoF09/index.m3u8\n" +
                        "第16集$https://cdn.605-zy.com/20211103/ujRdXTFK/index.m3u8\n" +
                        "第17集$https://cdn.605-zy.com/20211109/BSgGWGzz/index.m3u8");
            }
        } catch (UnsupportedFlavorException unsupportedFlavorException) {
            unsupportedFlavorException.printStackTrace();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    private int checkUrl(int i, String url, TaskInfo taskInfo) {
        if (StringUtils.contains(url, "$")) {
            String[] str = StringUtils.split(url, "$");
            if (str.length > 1) {
                if (StringUtils.contains(str[0], "http")) {
                    taskInfo.setUrl(str[0]);
                    taskInfo.setName(str[1]);
                }
                if (StringUtils.contains(str[1], "http")) {
                    taskInfo.setUrl(str[1]);
                    taskInfo.setName(str[0]);
                }
            }
        } else {
            taskInfo.setUrl(url);
            taskInfo.setName("第" + (i++) + "集");
        }
        return i;
    }

    /**
     * 退出程序
     */
    public void closeAction()  {
        System.exit(0);
    }

    /**
     * 删除任务
     */
    public void deleteDataAction() {
        Platform.runLater(() -> {
            removeDataAction();
        });
    }


    private void toAddForm(int index, String source) {
        log.info("调用添加数据");
        TaskInfoDataBase.INDEX = new TaskInfoDataBase.Index(index, source);
        if (!EditTaskForm.isShow()) {
            EditTaskForm.show();
        }
    }

    private void removeDataAction() {
        TableViewSelectionModel<TaskInfo> model = tableView.getSelectionModel();
        ObservableList<TaskInfo> selectedItems = model.getSelectedItems();
        List<TaskInfo> temp = new ArrayList<>();
        selectedItems.stream().forEach(temp::add);
        temp.stream().forEach(taskInfo -> {
            log.info("移除任务：{}", taskInfo.getName());
            DownloadM3u8 download = TaskInfoDataBase.DOWNLOADING_M3U8.get(taskInfo.getUrl());
            if (download != null) {
                MainTaskTreadPool.getINSTANCE().remove(TaskInfoDataBase.DOWNLOADING_M3U8.get(taskInfo.getUrl()));
                synchronized (this) {
                    download.close();
                }
                //引用类型为空时，会触发垃圾回收机制
                download = null;
                TaskInfoDataBase.DOWNLOADING_M3U8.remove(taskInfo.getUrl());
                //删除下载的文件
                deleteFiles(taskInfo);
            }
            TaskInfoDataBase.DATABASE.remove(taskInfo);
        });
        tableView.setItems(TaskInfoDataBase.DATABASE);
    }



    public void initDatabase() {
        log.info("调用初始化数据");
        if (file.exists()) {
            SeriaUtil.readData();
        } else {
            SeriaUtil.writeData();
        }
    }


    public void checkUpdate() throws IOException {
        Response response = HttpUtil.okHttpGet("https://gitee.com/club-du/m3u8_tool/blob/master/src/main/resources/com/micro/version", new RequestHeader.Build().build().addHeader("Accept", "application/json"));
        String body = response.body().string();
        Map<String, Object> bodyMap = JsonUtil.toObject(body, Map.class);
        if (bodyMap != null && !bodyMap.isEmpty()) {
            if (!StringUtils.equals(ConfigInfo.VERSION, String.valueOf(bodyMap.get("raw_content")))) {
                Desktop.getDesktop().browse(URI.create("https://gitee.com/club-du/m3u8_tool"));
            } else {
                JOptionPane.showConfirmDialog(null, "已是最新版本");
            }
        }
    }

    public void shutdownAction(ActionEvent actionEvent) {
        rebootCheck.setSelected(false);
        dormancyCheck.setSelected(false);
        ConfigInfo.setIsShutdown(shutdownCheck.isSelected());
        ConfigInfo.setIsDormancy(dormancyCheck.isSelected());
        ConfigInfo.setIsReboot(rebootCheck.isSelected());

    }

    public void dormancyAction(ActionEvent actionEvent) {
        shutdownCheck.setSelected(false);
        rebootCheck.setSelected(false);
        ConfigInfo.setIsShutdown(shutdownCheck.isSelected());
        ConfigInfo.setIsDormancy(dormancyCheck.isSelected());
        ConfigInfo.setIsReboot(rebootCheck.isSelected());
    }

    public void rebootAction(ActionEvent actionEvent) {
        shutdownCheck.setSelected(false);
        dormancyCheck.setSelected(false);
        ConfigInfo.setIsShutdown(shutdownCheck.isSelected());
        ConfigInfo.setIsDormancy(dormancyCheck.isSelected());
        ConfigInfo.setIsReboot(rebootCheck.isSelected());
    }

    public void setting(ActionEvent actionEvent) {
        SettingsForm.show();
    }

    public void about(ActionEvent actionEvent) {
        AboutForm.show();
    }

    public void open(ActionEvent actionEvent) throws IOException {
        Desktop.getDesktop().browse(URI.create("https://gitee.com/club-du/m3u8_tool"));
    }
}
